/*
 * Copyright 2009-2009 Tanesha Project. All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without modification, 
 * are permitted provided that the following conditions are met:
 * 
 *    1. Redistributions of source code must retain the above copyright notice, 
 *    	 this list of conditions and the following disclaimer.
 *    2. Redistributions in binary form must reproduce the above copyright notice,
 *    	 this list of conditions and the following disclaimer in the documentation 
 *    	 and/or other materials provided with the distribution.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE FREEBSD PROJECT ``AS IS'' AND ANY EXPRESS OR 
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 
 * SHALL THE FREEBSD PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 
 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 
 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 *  OF THE POSSIBILITY OF SUCH DAMAGE.
 * 
 * The views and conclusions contained in the software and documentation are those 
 * of the authors and should not be interpreted as representing official policies, 
 * either expressed or implied, of the Tanesha Project.
 */
package com.google.api.chart.encoding;

import java.lang.reflect.Array;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class JoinHelper {
	
	public static ToStringHelper<Object> TO_STRING_JOIN = new ToStringHelper<Object>() {
		@Override public String string(Object obj) { return obj.toString(); }
	};

	public static interface ToStringHelper<T> {
		public String string(T obj);
	}
	
	public static interface MapHelper<T, E> {
		public E map(T obj);
	}

	public static interface FilterHelper<T> {
		public boolean accept(T obj);
	}
	
	public static String doubleFormat(double d) {
		String s = BigDecimal.valueOf(d).stripTrailingZeros().toPlainString();
		// hm, it doesn't strip trailing zeros from 0.0 ? :-S  this hacky but ok.
		if ("0.0".equals(s))
			return "0";
		else
			return s;
	}

	public static <T> T[] filter(T[] arr, Class<T> clazz, FilterHelper<T> helper) {
		// nothing to filter
		if (arr.length == 0)
			return arr;
		// construct filtered array
		List<T> res = new ArrayList<T>();
		for (int i = 0; i < arr.length; i++) {
			if (helper.accept(arr[i]))
				res.add(arr[i]);
		}
		// create array to map into (arr[0] != null)
		T[] resA = (T[]) Array.newInstance(clazz, res.size());
		return res.toArray(resA);
	}
	
	
	public static <T, E> E[] map(T[] arr, Class<E> clazz, MapHelper<T, E> helper) {
		E[] res = (E[]) Array.newInstance(clazz, arr.length);
		for (int i = 0; i < arr.length; i++) {
			res[i] = helper.map(arr[i]);
		}
		return res;
	}
	
	public static List<BigDecimal[]> dataSet(int[][] values) {
		
		List<BigDecimal[]> res = new ArrayList<BigDecimal[]>();
		for (int i = 0; i < values.length; i++) {
			BigDecimal[] tmp = new BigDecimal[values[i].length];
			for (int j = 0; j < values[i].length; j++) {
				tmp[j] = BigDecimal.valueOf(values[i][j]);
			}
			res.add(tmp);
		}

		return res;
	}
	
	public static <E> E[] array(List<E> list, Class<E> clazz) {
		E[] res = (E[]) Array.newInstance(clazz, list.size());
		int i = 0;
		for (Iterator<E> it = list.iterator(); it.hasNext(); ) {
			res[i++] = it.next();
		}
		return res;
	}
	
	public static <T, E> List<E> map(List<T> list, MapHelper<T, E> helper) {
		List<E> res = new ArrayList<E>();
		for (Iterator<T> it = list.iterator(); it.hasNext(); ) {
			res.add(helper.map(it.next()));
		}
		return res;
	}
	
	public static <T> String join(T[] arr, String delim, ToStringHelper<T> helper) {
		StringBuilder buf = new StringBuilder();
		for (T obj : arr) {
			if (buf.length() == 0) {
				buf.append(helper.string(obj));
			}
			else {
				buf.append(delim).append(helper.string(obj));
			}
		}
		return buf.toString();
	}
	
	public static String join(Object[] arr, String delim) {
		return join(arr, delim, TO_STRING_JOIN);
	}
	
	public static String join(double[] arr, String delim) {
		Double[] d = new Double[arr.length];
		for (int i = 0; i < d.length; i++)
			d[i] = arr[i];
		return join(d, delim);
	}
	
	public static FilterHelper<String> notNullFilter = new FilterHelper<String>() {
		@Override public boolean accept(String obj) {
			if (obj == null)
				return false;
			else
				return true;
		}
	};


}
